﻿using System;
using System.ComponentModel;
using System.Xml.Serialization;
using Microsoft.WowAddonStudio.FrameXml.Serialization.Attributes;
using Microsoft.WowAddonStudio.FrameXml.Serialization.TypeConverters;

namespace Microsoft.WowAddonStudio.FrameXml.Serialization
{
    [Serializable]
    [DesignerCategory("code")]
    [XmlType(Namespace = "http://www.blizzard.com/wow/ui/")]
	[TypeConverter(typeof(ShadowTypeConverter))]
    public class Shadow : SerializationObject, ICloneable, ICopiable<Shadow>, IEquatable<Shadow>
    {
        /// <summary>
        /// Gets or sets the offset of the shadow.
        /// </summary>
        [XmlElement]
        [NotifyParentProperty(true)]
		[RefreshProperties(RefreshProperties.All)]
		[Category("Layout")]
        public Dimension Offset { get; set; }

        /// <summary>
        /// Gets or sets the color of the shadow.
        /// </summary>
        [XmlElement]
        [NotifyParentProperty(true)]
		[RefreshProperties(RefreshProperties.All)]
		[Category("Appearance")]
		[EditorBrowsable]
		[Description("The color used to display shadow.")]
        [Color]
        public Color Color { get; set; }

        /// <summary>
        /// Gets a value indicating whether a serialization object is complete and can be rendered.
        /// </summary>
        /// <value></value>
        [XmlIgnore]
        public override bool IsComplete
        {
            get
            {
                return Offset != null && Offset.IsAbsolute && Color != null;
            }
        }

        /// <summary>
        /// Creates a new object that is a copy of the instance.
        /// </summary>
        /// <returns>The copied instance.</returns>
        /// <remarks>Performs a deep copy.</remarks>
        public Shadow Copy()
        {
            return new Shadow
            {
                Color = Color != null ? Color.Copy() : null,
                Offset = Offset != null ? Offset.Copy() : null
            };
        }

        /// <summary>
        /// Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>The cloned instance.</returns>
        public object Clone()
        {
            return this.Copy();
        }

        /// <summary>
        /// Equalses the specified other.
        /// </summary>
        /// <param name="other">The obj.</param>
        /// <returns></returns>
        public bool Equals(Shadow other)
        {
            if (ReferenceEquals(null, other))
                return false;
            if (ReferenceEquals(this, other))
                return true;

            return Equals(other.Offset, Offset) && Equals(other.Color, Color);
        }

        /// <summary>
        /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
        /// </summary>
        /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.</param>
        /// <returns>
        /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
        /// </returns>
        /// <exception cref="T:System.NullReferenceException">
        /// The <paramref name="obj"/> parameter is null.
        /// </exception>
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
                return false;
            if (ReferenceEquals(this, obj))
                return true;
            if (obj.GetType() != typeof (Shadow))
                return false;

            return Equals((Shadow) obj);
        }

        /// <summary>
        /// Serves as a hash function for a particular type.
        /// </summary>
        /// <returns>
        /// A hash code for the current <see cref="T:System.Object"/>.
        /// </returns>
        public override int GetHashCode()
        {
            unchecked
            {
                return ((Offset != null ? Offset.GetHashCode() : 0)*397) ^ (Color != null ? Color.GetHashCode() : 0);
            }
        }


        /// <summary>
        /// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
        /// </summary>
        /// <returns>
        /// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
        /// </returns>
        public override string ToString()
        {
            return string.Format("{0} {1}", Color, Offset);
        }
    }
}